package com.gopay.scheduler.service.jobmonitor.impl;

import java.util.*;

import javax.annotation.Resource;

import com.gopay.common.constants.cust.SMSType;
import com.gopay.scheduler.common.SendMsg;
import org.quartz.*;
import org.quartz.impl.StdScheduler;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.gopay.remote.monitor.JobMonitorWeixinRemoteService;

/**
 * Job监控辅助类
 * 
 * @JobMonitorHelper.java
 * @author fanghw
 * @2015年5月8日 下午4:04:55 www.gopay.com.cn Inc.All rights reserved.
 */
public class JobMonitorHelper implements ApplicationContextAware {
    
    // 日志
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    
    private ApplicationContext applicationContext;
	//限制报警短信次数
	private static Integer sendTime = 0;
	//熔断报警临界值
	private static Integer breakerCount = 0;
	//线程阻塞临界值
	private final static Integer CRONTHREAD_NUM = 9;

	private StdScheduler schFactoryBean;
    
    @Resource(name = "jobMonitorWeixinClient")
    private JobMonitorWeixinRemoteService jobMonitorWeixinClient;

	@Resource(name = "sendMsg")
	private SendMsg sendMsg;

	@Value("#{webProperties['jobCron.sms.switch']}")
	private String jobCronSwitch;

	private static final String SWITCH_ON = "on";

	@Value("#{webProperties['jobCron.recvMobile']}")
	private String recvMobile;

	private Set<Trigger> blockedTrigger = new LinkedHashSet<>();

	/**
     * 查询异常状态的Job
     * @return
     */
	public List<String> queryErrorJob() {
		blockedTrigger.clear();
		List<String> jobList = new ArrayList<String>();
		if(schFactoryBean==null){
			schFactoryBean=(StdScheduler)applicationContext.getBean("allStartQuertz");
		}
		try {
			List<String> triggerGroupNames = schFactoryBean.getTriggerGroupNames();
			Trigger.TriggerState state;
			Trigger trigger;
			for(String triggerGroupName : triggerGroupNames) {
				Set<TriggerKey> triggerKeys =  schFactoryBean.getTriggerKeys(GroupMatcher.triggerGroupEquals(triggerGroupName));

				for (TriggerKey triggerKey : triggerKeys) {
					trigger = schFactoryBean.getTrigger(triggerKey);
					String jobName = trigger.getJobKey().getName();
					state = schFactoryBean.getTriggerState(triggerKey);
					switch (state) {
						case NONE:
						case ERROR:
							jobList.add(jobName);
							break;
						case BLOCKED:
							blockedTrigger.add(trigger);
							break;
					}
				}
				logger.info(String.format("**************阻塞trigger:%s,size:%s*************" , blockedTrigger,blockedTrigger.size()));
				//熔断机制
				if(blockedTrigger.size() >= CRONTHREAD_NUM){
					breakerCount++;
					logger.info("***************熔断计数:" + breakerCount);
					if(sendTime < 1 && breakerCount >= 3){
						sendTime++;
						if(SWITCH_ON.equals(jobCronSwitch))
							sendMsg.sendSms(recvMobile, "quartz监控job调度线程频繁超过80%，可能引发异常，请您处理！！", SMSType.OTHER_SMS);
						else
							logger.info("cron预警短信已关闭：quartz监控job调度线程频繁超过80%，可能引发异常，请您处理！！");
					}
				}else{breakerCount = 0;}
			}
		} catch (SchedulerException e) {
			logger.error("任务监控Job异常", e);
		}
		return jobList;
	}
    
    /**
     * 发送微信
     * @param content
     * @return
     */
    public boolean sendWeixin(String content){        
        return jobMonitorWeixinClient.sendExcepNews(content);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
    }

	public void setSchFactoryBean(StdScheduler schFactoryBean) {
		this.schFactoryBean = schFactoryBean;
	}

	public StdScheduler getSchFactoryBean() {
		return schFactoryBean;
	}

}
